//
// Created by cljh on 2023/3/30.
//

#ifndef BIN_PACKING_MATPLOTLIB_H
#define BIN_PACKING_MATPLOTLIB_H
#include <matplotlibcpp.h>
#include "../entity/Polygon.h"
#include "../entity/NestPath.h"
#include "ClipperUtil.h"
#include "../algorithm/Nest.h"

namespace plt = matplotlibcpp;
class Matplotlib {
public:
    static void buildPolygonVector(Polygon *polygon,std::vector<double> &x,std::vector<double> &y){
        Vector shiftVector=polygon->offset;
        for(int i=0;i<polygon->lenth;i++){
            x.push_back(polygon->getx(i)+shiftVector.x);
            y.push_back(polygon->gety(i)+shiftVector.y);
        }
        if(polygon->lenth>1){
            x.push_back(polygon->getx(0)+shiftVector.x);
            y.push_back(polygon->gety(0)+shiftVector.y);
        }
        return;
    }
    static void displayPolygon(Polygon &polygon){
        std::vector<double> x=std::vector<double>();
        std::vector<double> y=std::vector<double>();
        Vector shiftVector=polygon.offset;
        for(int i=0;i<polygon.lenth;i++){
            x.push_back(polygon.getx(i)+shiftVector.x);
            y.push_back(polygon.gety(i)+shiftVector.y);
        }
        if(polygon.lenth>1){
            x.push_back(polygon.getx(0)+shiftVector.x);
            y.push_back(polygon.gety(0)+shiftVector.y);
        }
//        plt::xkcd();
        plt::plot(x,y);
        plt::show();
        return;
    }
    static void displayNestPaths(std::vector<NestPath> nestPaths) {
        for(int j=0;j<nestPaths.size();j++){
            NestPath nestPath=nestPaths[j];
            for (int i = 0; i < nestPath.size(); i++) {
                std::vector<double> x=std::vector<double>();
                std::vector<double> y=std::vector<double>();
                Polygon *polygon=nestPath[i];
                buildPolygonVector(polygon,x,y);
                plt::plot(x,y);
            }
        }
        plt::show();
        return;
    }
    static void displayNestPath(NestPath nestPath) {
        for (int i = 0; i < nestPath.size(); i++) {
            std::vector<double> x=std::vector<double>();
            std::vector<double> y=std::vector<double>();
            Polygon *polygon=nestPath[i];
            buildPolygonVector(polygon,x,y);
            plt::plot(x,y);
        }
        plt::show();
        return;
    }
    static void displayNest(Nest nest){
        NestPath bin=nest.bin;
        Individual individual=nest.bestIndividual;
        std::vector<NestPath> parts=individual.paths;
        std::vector<Vector> placement=individual.placement;
        for (int i = 0; i < bin.size(); i++) {
            std::vector<double> x=std::vector<double>();
            std::vector<double> y=std::vector<double>();
            Polygon *polygon=bin[i];
            buildPolygonVector(polygon,x,y);
            plt::plot(x,y);
        }
        std::cout<<"part size is: "<<parts.size()<<std::endl;
        for(int i=0;i<parts.size();i++){
            NestPath path=parts[i];
            int angle=path.rotation;
            for(int j=0;j<path.size();j++){
                std::vector<double> x=std::vector<double>();
                std::vector<double> y=std::vector<double>();
                Polygon *polygon=GeometryUtils::rotatePolygon(path[j],angle);
                polygon->offset=placement[i];
                buildPolygonVector(polygon,x,y);
                plt::plot(x,y);
            }
        }
        plt::show();
    }

    static void showClipper(Clipper2Lib::Paths64 paths){
        for(int i=0;i<paths.size();i++){
            std::vector<double> x=std::vector<double>();
            std::vector<double> y=std::vector<double>();
            Clipper2Lib::Path64 path=paths[i];
            for(int j=0;j<path.size();j++){
                Clipper2Lib::Point64 point=path[j];
                x.push_back(point.x);
                y.push_back(point.y);
            }
            x.push_back(path[0].x);
            y.push_back(path[0].y);
            plt::plot(x,y);
        }
        plt::show();
        return;
    }
    static void showClippers64(std::vector<Clipper2Lib::Paths64> pathsVector){
        for(int k=0;k<pathsVector.size();k++){
            Clipper2Lib::Paths64 paths=pathsVector[k];
            for(int i=0;i<paths.size();i++){
                std::vector<double> x=std::vector<double>();
                std::vector<double> y=std::vector<double>();
                Clipper2Lib::Path64 path=paths[i];
                for(int j=0;j<path.size();j++){
                    Clipper2Lib::Point64 point=path[j];
                    x.push_back(point.x);
                    y.push_back(point.y);
                }
                x.push_back(path[0].x);
                y.push_back(path[0].y);
                plt::plot(x,y);
            }
        }
        plt::show();
        return;
    }
    static void showClippersD(std::vector<Clipper2Lib::PathsD> pathsVector){
        for(int k=0;k<pathsVector.size();k++){
            Clipper2Lib::PathsD paths=pathsVector[k];
            for(int i=0;i<paths.size();i++){
                std::vector<double> x=std::vector<double>();
                std::vector<double> y=std::vector<double>();
                Clipper2Lib::PathD path=paths[i];
                for(int j=0;j<path.size();j++){
                    Clipper2Lib::PointD point=path[j];
                    x.push_back(point.x);
                    y.push_back(point.y);
                }
                x.push_back(path[0].x);
                y.push_back(path[0].y);
                plt::plot(x,y);
            }
        }
        plt::show();
        return;
    }
};


#endif //BIN_PACKING_MATPLOTLIB_H
